package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"syscall"
)

func doServerStuff(conn net.Conn) {
	for {
		buf := make([]byte, 512)
		len, err := conn.Read(buf)
		if err != nil{
			fmt.Println("Error reading", err.Error())
			return
		}
		fmt.Printf("Received data: %v\n", string(buf[:len]))
	}
}

func serverTest() {
	fmt.Println("Starting the server...")
	listener, err := net.Listen("tcp", "localhost:50000")
	if err != nil{
		fmt.Println("Error listening", err.Error())
		return
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Error accepting", err.Error())
			return
		}

		go doServerStuff(conn)
	}
}


func serverTest1() {
	var (
		host 			= "www.baidu.com"
		port			= "80"
		remote			= host + ":" + port
		msg  string		= "GET / \n"
		data 			= make([]uint8, 4096)
		read 			= true
		count 			= 0
	)

	con, err := net.Dial("tcp", remote)
	io.WriteString(con, msg)
	for read {
		count, err = con.Read(data)
		read = (err == nil)
		fmt.Printf(string(data[0:count]))
	}
	con.Close()

}

const maxRead = 25

func initServer(hostAndPort string) *net.TCPListener {
	serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
	checkError(err, "Resolving address:port failed: '" + hostAndPort + "'")
	listener, err := net.ListenTCP("tcp", serverAddr)
	checkError(err, "ListenTCP")
	println("Listening to: ", listener.Addr().String())
	return listener
}

func connectionHandler(conn net.Conn) {
	connFrom := conn.RemoteAddr().String()
	println("Connection from: ", connFrom)
	sayHello(conn)
	for {
		var ibuf []byte = make([]byte, maxRead + 1)
		length, err := conn.Read(ibuf[0:maxRead])
		ibuf[maxRead] = 0
		switch err {
		case nil:
			handleMsg(length, err, ibuf)
		case syscall.EAGAIN:
			continue
		default:
			goto DISCONNECT

			
		}
	}
DISCONNECT:
	err := conn.Close()
	println("Closed connection: ", connFrom)
	checkError(err, "Close: ")
}

func sayHello(to net.Conn) {
	obuf := []byte{'L', 'e', 't', '\'', 's', ' ', 'G', 'O', '!', '\n'}
	wrote, err := to.Write(obuf)
	checkError(err, "Write: wrote " + string(wrote) + " bytes.")
}

func handleMsg(length int, err error, msg []byte) {
	if length > 0{
		print("<", length, ":")
		for i := 0; ; i++ {
			if msg[i] == 0 {
				break
			}
			fmt.Printf("%c", msg[i])
		}
		print(">")
	}
}

func checkError(error error, info string) {
	if error != nil{
		panic(any("ERROR: " + info + " " + error.Error()))
	}
}

func serverTest2() {
	flag.Parse()
	if flag.NArg() != 2{
		panic(any("usage: host port"))
	}
	hsotAndPort := fmt.Sprintf("%s:%s", flag.Arg(0), flag.Arg(1))
	listener := initServer(hsotAndPort)
	for {
		conn, err := listener.Accept()
		checkError(err, "Accept： ")
		go connectionHandler(conn)
	}
}

func helloServer(w http.ResponseWriter, req *http.Request) {
	fmt.Println("Inside HelloServer handler")
	fmt.Fprintf(w, "Hello, " + req.URL.Path[1:])
}

func httpServerTest() {
	http.HandleFunc("/", helloServer)
	err := http.ListenAndServe("localhost:8080", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.Error())
	}

}

var urls = []string{
	"http://www.google.com/",
	"http://golang.org/",
	"http://blog.golang.org/",
}

func httpTest2() {
	for _, url := range urls{
		resp, err := http.Head(url)
		if err != nil{
			fmt.Println("Error: ", url, err)
		}
		fmt.Println(url, ": ", resp.Status)
	}
}

func main() {
	//serverTest()
	//serverTest1()
	//serverTest2()
	//httpServerTest()
	httpTest2()

}
